package com.cqdev.washer.biz.service;

import com.cqdev.washer.biz.enums.ProjectExecuteStatusEnum;
import com.cqdev.washer.biz.enums.ScriptExecuteResultEnum;
import com.cqdev.washer.biz.model.ProjectBO;
import com.cqdev.washer.biz.model.SqlScriptBO;
import com.cqdev.washer.infra.service.JdbcTemplateService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;

import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * @author yunfei.li
 *         类描述: TODO
 *         日期： 2018/6/22
 */
@Service
@Slf4j
public class ExecuteService {
    private final ProjectService projectService;
    private final ScriptService scriptService;

    private final JdbcTemplateService jdbcTemplateService;

    public ExecuteService(ProjectService projectService, ScriptService scriptService, JdbcTemplateService jdbcTemplateService) {
        this.projectService = projectService;
        this.scriptService = scriptService;
        this.jdbcTemplateService = jdbcTemplateService;
    }

    public void exec(Long projectId) {
        if (projectId == null) {
            return;
        }
        ProjectBO one = projectService.getOne(projectId);
        if (one.getProjectExecuteStatusEnum() == ProjectExecuteStatusEnum.DOING) {
            return;
        }
        projectService.start(one);

        List<SqlScriptBO> sqlScriptBOList = one.getSqlScriptBOList().stream().sorted(Comparator.comparing(SqlScriptBO::getSn)).collect(Collectors.toList());

        JdbcTemplate jdbcTemplate = jdbcTemplateService.jdbcTemplate(one.getDbConfigBO());

        sqlScriptBOList.forEach(scriptBO -> {
            execution(jdbcTemplate, scriptBO);
        });

        projectService.shutdown(one);

    }

    public void exec(Long projectId, Long scriptId) {
        ProjectBO one = projectService.getOne(projectId);
        Optional<SqlScriptBO> first = one.getSqlScriptBOList().stream().filter(sqlScriptBO -> Objects.equals(sqlScriptBO.getId(), scriptId)).findFirst();
        if (!first.isPresent()) {
            throw new RuntimeException("script find not found.");
        }
        SqlScriptBO sqlScriptBO = first.get();
        JdbcTemplate jdbcTemplate = jdbcTemplateService.jdbcTemplate(one.getDbConfigBO());

        execution(jdbcTemplate, sqlScriptBO);

    }

    private void execution(JdbcTemplate jdbcTemplate, SqlScriptBO sqlScriptBO) {
        if (sqlScriptBO == null || jdbcTemplate == null) {
            throw new RuntimeException("service exception");
        }
        log.info("execute sql = {}", sqlScriptBO);
        try {
            long startTime = System.currentTimeMillis();
            jdbcTemplate.execute(sqlScriptBO.getScript());
            long endTime = System.currentTimeMillis();
            long elapsedTime = endTime - startTime;
            sqlScriptBO.setLastElapsedTime(elapsedTime);

            scriptService.updateScriptStatus(sqlScriptBO, ScriptExecuteResultEnum.SUCCESS);
        } catch (Exception e) {
            scriptService.updateScriptStatus(sqlScriptBO, ScriptExecuteResultEnum.FAIL);
            log.error("execute script error = {} ", e);
        }
    }
}
